package com.example.block_chain.service.impl;

import com.alibaba.fastjson2.JSON;
import com.example.block_chain.common.AppHttpCodeEnum;
import com.example.block_chain.exception.SystemException;
import com.example.block_chain.service.OSSUploadService;
import com.example.block_chain.utils.UidUtil;
import com.qiniu.http.Response;
import com.qiniu.storage.Configuration;
import com.qiniu.storage.Region;
import com.qiniu.storage.UploadManager;
import com.qiniu.storage.model.DefaultPutRet;
import com.qiniu.storage.persistent.FileRecorder;
import com.qiniu.util.Auth;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;

/*
 *@description: 文件上传业务实现类
 *@author: hisen
 *@Time: 2023/10/26  18:08
 */
@Component
@Data
@Slf4j
@ConfigurationProperties(
        prefix = "oss"
)
public class OSSUploadServiceImpl implements OSSUploadService {
    private String accessKey;
    private String secretKey;
    private String bucket;
    private String CDN;

    /**
     * 断点续传
     * @param inputStream 输入流
     * @return 文件连接
     */

    @Override
    public String resumeUpload(InputStream inputStream) throws IOException {
        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(Region.huabei());
        cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
        cfg.resumableUploadMaxConcurrentTaskCount = 2;  // 设置分片上传并发，1：采用同步上传；大于1：采用并发上传
        //...其他参数参考类注释
        //byte[] fileBytes = file.getBytes();
        //默认不指定key的情况下，以文件内容的hash值作为文件名
        String key = UidUtil.getUid();

        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);

        String localTempDir = Paths.get(System.getenv("java.io.tmpdir"), bucket).toString();

        //设置断点续传文件进度保存目录
        FileRecorder fileRecorder = new FileRecorder(localTempDir);
        UploadManager uploadManager = new UploadManager(cfg, fileRecorder);

        Response response;

        response = uploadManager.put(inputStream, key, upToken,null,null);
        inputStream.close();
        //解析上传成功的结果
        DefaultPutRet putRet = JSON.parseObject(response.bodyString(), DefaultPutRet.class);

        return CDN+putRet.key;
    }

    @Override
    public List<String> getImagesUrl(List<String> filesName) {

        Auth auth = Auth.create(accessKey, secretKey);
        long expireInSeconds = 3600;//1小时，可以自定义链接过期时间
        return filesName.stream().map(name -> auth.privateDownloadUrl(name, expireInSeconds)).collect(Collectors.toList());
    }

    public void uploadImg(MultipartFile img) {
        String originalFilename = img.getOriginalFilename();
        //判断文件类型是否是图片
        if (originalFilename == null||(!originalFilename.toLowerCase().endsWith(".jpg") &&
                !originalFilename.toLowerCase().endsWith(".png"))) {
            throw new SystemException(AppHttpCodeEnum.FILE_TYPE_ERROR);
        }
    }

    /**
     * 分片上传
     *
     * @param fileStream 输入流
     * @param fileDir
     */
    @Override
    public String upload(InputStream fileStream, String fileDir) throws IOException {
        //构造一个带指定 Region 对象的配置类
        Configuration cfg = new Configuration(Region.autoRegion());
        cfg.resumableUploadAPIVersion = Configuration.ResumableUploadAPIVersion.V2;// 指定分片上传版本
        //...其他参数参考类注释
        UploadManager uploadManager = new UploadManager(cfg);
        Auth auth = Auth.create(accessKey, secretKey);
        String upToken = auth.uploadToken(bucket);
        String key = UidUtil.getUid();
        Response response = uploadManager.put(fileStream, fileDir+key,upToken,null, null);
        fileStream.close();
        //解析上传成功的结果
        DefaultPutRet putRet = JSON.parseObject(response.bodyString(), DefaultPutRet.class);
        return CDN+putRet.key;
    }
}
